package com.hyt.it.ogt.kq.service.admission.impl;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN;
import static com.hyt.it.ogt.kq.common.gov.enums.admission.TemplateTypeEnum.STANDARD_1;
import static com.hyt.it.ogt.kq.common.gov.enums.admission.TemplateTypeEnum.STANDARD_2;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hyt.core.base.BaseEntity;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.gov.constant.admission.AdmissionTicketTemplateCode;
import com.hyt.it.ogt.kq.common.gov.enums.admission.NotRoomCustomTemplateConfigEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.Standard1TemplateConfigCode;
import com.hyt.it.ogt.kq.common.gov.enums.admission.Standard2TemplateConfigCode;
import com.hyt.it.ogt.kq.common.gov.enums.admission.TicketDataSourceEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.VirtualCustomTemplateConfigEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.variable.CustomTemplateConfigCode;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketInfoService;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketTemplateService;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketTemplateVariableService;
import com.hyt.it.ogt.kq.service.gov.feign.ks.KsFallbackFactoryClient;
import com.hyt.it.ogt.kq.service.gov.feign.ks.model.KwExamVO;
import com.hyt.it.ogt.kq.service.gov.mapper.admission.AdmissionTicketTemplateVariableMapper;
import com.hyt.it.ogt.kq.service.gov.model.dto.admission.AdmissionTicketTemplateVariableDTO;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.param.admission.AddOrUpdateAdmissionTicketInfoParam;
import com.hyt.it.ogt.kq.service.gov.service.IExamAgreementService;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketInfo;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketTemplate;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketTemplateVariable;
import com.hyt.loginfo.model.Organization;
import com.hyt.loginfo.model.User;

import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 准考证模板变量表 服务实现类
 * </p>
 *
 * @author yanghuankun@talkweb.com.cn
 * @since 2023-01-10
 */
@Service
@Slf4j
public class AdmissionTicketTemplateVariableServiceImpl extends BaseServiceImpl<AdmissionTicketTemplateVariableMapper, AdmissionTicketTemplateVariable> implements IAdmissionTicketTemplateVariableService {
	@Resource
    private IAdmissionTicketInfoService iAdmissionTicketInfoService;
    @Resource
    private IAdmissionTicketTemplateService iAdmissionTicketTemplateService;
    @Resource
    private KsFallbackFactoryClient ksFallbackFactoryClient;
    @Resource
    private ITaskService iTaskService;
    @Resource
    private ConfigManager configManager;
    @Resource
    private IExamAgreementService iExamAgreementService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(List<AdmissionTicketTemplateVariableDTO> admissionTicketTemplateVariableDTOS, String admissionId, User user, Organization deptInfo) {
        // 删除旧的模板变量
        LocalDateTime now = LocalDateTime.now();
        lambdaUpdate()
                .eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionId)
                .notIn(AdmissionTicketTemplateVariable::getVariableCode, AdmissionTicketTemplateCode.publicCode())
                .set(BaseEntity::getDelFlag, true)
                .set(BaseEntity::getUpdateBy, user.getId())
                .set(BaseEntity::getUpdateDate, now)
                .update();

        // 新增新的模板变量
        AdmissionTicketInfo admissionTicketInfo = iAdmissionTicketInfoService.getById(admissionId);
        Integer admissionTicketDataSource = admissionTicketInfo.getAdmissionTicketDataSource();
        List<AdmissionTicketTemplateVariable> admissionTicketTemplateVariables = new ArrayList<>(admissionTicketTemplateVariableDTOS.size());
        boolean isNotRoom = Objects.equals(TicketDataSourceEnum.NOT_ROOM.getCode(), admissionTicketDataSource);
        KwExamVO kwExamVO = null;
        Task task = null;
        if (isNotRoom) {
            // 无考场查询信息
            kwExamVO = ksFallbackFactoryClient.exam(admissionTicketInfo.getOfficeId(), admissionTicketInfo.getDeptId(), admissionTicketInfo.getExamId()).getData();
        } else {
            // 虚拟考场查询信息
            task = iTaskService.getById(admissionTicketInfo.getExamId());
        }

        AdmissionTicketTemplate admissionTicketTemplate = iAdmissionTicketTemplateService.getByAdmissionInfoId(admissionId);
        for (AdmissionTicketTemplateVariableDTO admissionTicketTemplateVariableDTO : admissionTicketTemplateVariableDTOS) {
            AdmissionTicketTemplateVariable admissionTicketTemplateVariable = new AdmissionTicketTemplateVariable();
            admissionTicketTemplateVariable.setId(UUIDUtils.newSortUUID());
            admissionTicketTemplateVariable.setCreateBy(user.getId());
            admissionTicketTemplateVariable.setCreateDate(now);
            admissionTicketTemplateVariable.setUpdateBy(user.getId());
            admissionTicketTemplateVariable.setUpdateDate(now);

            admissionTicketTemplateVariable.setAdmissionTicketId(admissionId);
            admissionTicketTemplateVariable.setTemplateId(admissionTicketTemplate.getId());
            admissionTicketTemplateVariable.setVariableCode(admissionTicketTemplateVariableDTO.getVariableCode());
            admissionTicketTemplateVariable.setVariableName(admissionTicketTemplateVariableDTO.getVariableName());
            if (isNotRoom) {
                if (NotRoomCustomTemplateConfigEnum.isKwPublicInfo(admissionTicketTemplateVariableDTO.getVariableCode())) {
                    admissionTicketTemplateVariable.setIsAllowUseDefault(true);
                    admissionTicketTemplateVariable.setVariableDefaultValue(getKwValue(admissionTicketTemplateVariableDTO.getVariableCode(), kwExamVO));
                }
            } else {
                if (VirtualCustomTemplateConfigEnum.isGovPublicInfo(admissionTicketTemplateVariableDTO.getVariableCode())) {
                    admissionTicketTemplateVariable.setIsAllowUseDefault(true);
                    admissionTicketTemplateVariable.setVariableDefaultValue(getGovValue(admissionTicketTemplateVariableDTO.getVariableCode(), task));
                }
            }
            admissionTicketTemplateVariable.setVariableSort(admissionTicketTemplateVariableDTO.getSort());
            admissionTicketTemplateVariable.setVariableDescription(admissionTicketTemplateVariableDTO.getDescription());
            admissionTicketTemplateVariables.add(admissionTicketTemplateVariable);
        }
        saveBatch(admissionTicketTemplateVariables);
    }

    public Set<String> getCustomTemplatePublicCode() {
        Set<String> codes = CustomTemplateConfigCode.publicConfigs().stream().map(CustomTemplateConfigCode::getCode).collect(Collectors.toSet());
        codes.add(AdmissionTicketTemplateCode.CERTIFICATE_PHOTO);
        return codes;
    }

    /**
     * 删除模板变量配置
     *
     * @param admissionId
     * @param currentUser
     */
    @Override
    public void deleteByAdmissionId(String admissionId, User currentUser) {
        lambdaUpdate()
                .eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionId)
                .set(AdmissionTicketTemplateVariable::getDelFlag, true)
                .set(AdmissionTicketTemplateVariable::getUpdateDate, LocalDateTime.now())
                .set(AdmissionTicketTemplateVariable::getUpdateBy, currentUser.getId())
                .update();
    }

    /**
     * 获取虚拟考场的公共值
     *
     * @param variableCode
     * @param task
     * @return
     */
    private String getGovValue(String variableCode, Task task) {
    	VirtualCustomTemplateConfigEnum virtualCustomTemplateConfigEnum = VirtualCustomTemplateConfigEnum.get(variableCode);
        switch (virtualCustomTemplateConfigEnum) {
            case EXAM_NAME:
                return task.getName();
            case EXAM_URL:
                return configManager.getOnlineExamUrl();
            default:
                return "";
        }
    }

    /**
     * 获取考试的公共值
     *
     * @param variableCode
     * @param kwExamVO
     * @return
     */
    private String getKwValue(String variableCode, KwExamVO kwExamVO) {
    	NotRoomCustomTemplateConfigEnum admissionVirtualInfoEnum = NotRoomCustomTemplateConfigEnum.get(variableCode);
        switch (admissionVirtualInfoEnum) {
            case EXAM_NAME:
                return kwExamVO.getExamName();
            case EXAM_START:
                return LocalDateTimeUtil.format(kwExamVO.getBeginDate(), NORM_DATETIME_PATTERN);
            case EXAM_END:
                return LocalDateTimeUtil.format(kwExamVO.getEndDate(), NORM_DATETIME_PATTERN);
            case EXAM_URL:
                return kwExamVO.getExamUrl();
            case EXAM_ID:
                return kwExamVO.getRandomId() + "";
            default:
                return "";
        }
    }

    /**
     * 初始化标准模板变量配置
     *
     * @param addOrUpdateAdmissionTicketInfoParam
     * @param admissionTicketInfoId
     * @param currentUser
     * @param deptId
     */
    @Override
    public void initStandardTemplateVariable(AddOrUpdateAdmissionTicketInfoParam addOrUpdateAdmissionTicketInfoParam, String admissionTicketInfoId, User currentUser, String deptId) {
        // 查询考试地址和考生协议
        String examUrl;
        String examAgreement;
        String examName;
        String examId = addOrUpdateAdmissionTicketInfoParam.getExamId();
        Task task = iTaskService.getById(examId);
        if (Objects.nonNull(task)) {
            // 虚拟考场
            examUrl = configManager.getOnlineExamUrl();
            examAgreement = iExamAgreementService.getExamAgreement(examId);
            examName = task.getName();
        } else {
            // 无考场
            KwExamVO kwExamVO = ksFallbackFactoryClient.exam(currentUser.getOfficeid(), deptId, examId).getData();
            examUrl = kwExamVO.getExamUrl();
            examAgreement = ksFallbackFactoryClient.exam(currentUser.getOfficeid(), deptId, examId).getData().getExamAgreement();
            examName = kwExamVO.getExamName();
        }

        List<AdmissionTicketTemplateVariable> admissionTicketTemplateVariables = new LinkedList<>();
        Integer templateType = addOrUpdateAdmissionTicketInfoParam.getTemplateType();
        if (Objects.equals(STANDARD_1.getCode(), templateType)) {
            // 标准模板1私有变量初始化
            for (Standard1TemplateConfigCode privateConfig : Standard1TemplateConfigCode.privateConfigs()) {
                AdmissionTicketTemplateVariable admissionTicketTemplateVariable = createAdmissionTicketTemplateVariable(currentUser,
                        admissionTicketInfoId, STANDARD_1.getCode() + "",
                        privateConfig.getCode(), privateConfig.getText(),
                        false, null);
                admissionTicketTemplateVariables.add(admissionTicketTemplateVariable);
            }
            // 标准模板1公共变量初始化
            for (Standard1TemplateConfigCode publicConfig : Standard1TemplateConfigCode.publicConfigs()) {
                String defaultValue = "";
                if (Objects.equals(Standard1TemplateConfigCode.PublicConfigCode.EXAM_URL, publicConfig)) {
                    defaultValue = examUrl;
                } else if (Objects.equals(Standard1TemplateConfigCode.PublicConfigCode.EXAM_AGREEMENT, publicConfig)) {
                    defaultValue = examAgreement;
                } else if (Objects.equals(Standard1TemplateConfigCode.PublicConfigCode.EXAM_NAME, publicConfig)) {
                    defaultValue = examName;
                } else if (Objects.equals(Standard1TemplateConfigCode.PublicConfigCode.CERTIFICATE_PHOTO, publicConfig)) {
                    defaultValue = configManager.getDefaultCertificatePhoto();
                }
                AdmissionTicketTemplateVariable admissionTicketTemplateVariable = createAdmissionTicketTemplateVariable(currentUser,
                        admissionTicketInfoId, STANDARD_1.getCode() + "",
                        publicConfig.getCode(), publicConfig.getText(),
                        true, defaultValue);
                admissionTicketTemplateVariables.add(admissionTicketTemplateVariable);
            }
        } else if (Objects.equals(STANDARD_2.getCode(), templateType)) {
            // 标准模板2私有变量初始化
            for (Standard2TemplateConfigCode privateConfig : Standard2TemplateConfigCode.privateConfigs()) {
                AdmissionTicketTemplateVariable admissionTicketTemplateVariable = createAdmissionTicketTemplateVariable(currentUser,
                        admissionTicketInfoId, STANDARD_2.getCode() + "",
                        privateConfig.getCode(), privateConfig.getText(),
                        false, null);
                admissionTicketTemplateVariables.add(admissionTicketTemplateVariable);
            }
            // 标准模板2公共变量初始化
            for (Standard2TemplateConfigCode publicConfig : Standard2TemplateConfigCode.publicConfigs()) {
                String defaultValue = "";
                if (Objects.equals(Standard2TemplateConfigCode.PublicConfigCode.EXAM_URL, publicConfig)) {
                    defaultValue = examUrl;
                } else if (Objects.equals(Standard2TemplateConfigCode.PublicConfigCode.EXAM_AGREEMENT, publicConfig)) {
                    defaultValue = examAgreement;
                } else if (Objects.equals(Standard2TemplateConfigCode.PublicConfigCode.EXAM_NAME, publicConfig)) {
                    defaultValue = examName;
                } else if (Objects.equals(Standard2TemplateConfigCode.PublicConfigCode.CERTIFICATE_PHOTO, publicConfig)) {
                    defaultValue = configManager.getDefaultCertificatePhoto();
                }
                AdmissionTicketTemplateVariable admissionTicketTemplateVariable = createAdmissionTicketTemplateVariable(currentUser,
                        admissionTicketInfoId, STANDARD_2.getCode() + "",
                        publicConfig.getCode(), publicConfig.getText(),
                        true, defaultValue);
                admissionTicketTemplateVariables.add(admissionTicketTemplateVariable);
            }
        }
        saveBatch(admissionTicketTemplateVariables);
    }

    /**
     * 标准模板创建变量配置
     *
     * @param currentUser
     * @param admissionTicketInfoId
     * @param templateId
     * @param code
     * @param name
     * @return
     */
    private AdmissionTicketTemplateVariable createAdmissionTicketTemplateVariable(User currentUser,
                                                                                  String admissionTicketInfoId, String templateId,
                                                                                  String code, String name,
                                                                                  boolean isAllowDefault, String defaultValue
    ) {
        LocalDateTime now = LocalDateTime.now();
        AdmissionTicketTemplateVariable admissionTicketTemplateVariable = new AdmissionTicketTemplateVariable();
        admissionTicketTemplateVariable.setId(UUIDUtils.newSortUUID());
        admissionTicketTemplateVariable.setCreateDate(now);
        admissionTicketTemplateVariable.setCreateBy(currentUser.getId());
        admissionTicketTemplateVariable.setUpdateDate(now);
        admissionTicketTemplateVariable.setUpdateBy(currentUser.getId());

        admissionTicketTemplateVariable.setAdmissionTicketId(admissionTicketInfoId);
        admissionTicketTemplateVariable.setTemplateId(templateId);
        admissionTicketTemplateVariable.setVariableCode(code);
        admissionTicketTemplateVariable.setVariableName(name);
        admissionTicketTemplateVariable.setIsAllowUseDefault(isAllowDefault);
        if (isAllowDefault) {
            admissionTicketTemplateVariable.setVariableDefaultValue(defaultValue);
        }
        return admissionTicketTemplateVariable;
    }

    /**
     * 初始化考生头像和考试协议变量配置
     *
     * @param templateId
     * @param admissionTicketInfoId
     * @param currentUser
     * @param deptId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void initCustomTemplateVariable(String templateId, String admissionTicketInfoId, User currentUser, String deptId) {
        List<AdmissionTicketTemplateVariable> admissionTicketTemplateVariables = new LinkedList<>();

        // 初始化照片
        AdmissionTicketTemplateVariable photo = createAdmissionTicketTemplateVariable(currentUser,
                admissionTicketInfoId, templateId,
                AdmissionTicketTemplateCode.CERTIFICATE_PHOTO, "证件照",
                false, null);
        admissionTicketTemplateVariables.add(photo);

        // 初始化考生协议
        AdmissionTicketInfo admissionTicketInfo = iAdmissionTicketInfoService.getById(admissionTicketInfoId);
        for (CustomTemplateConfigCode publicConfig : CustomTemplateConfigCode.publicConfigs()) {
            switch (publicConfig.getCode()) {
                case AdmissionTicketTemplateCode.EXAM_NAME:
                    AdmissionTicketTemplateVariable examName = createAdmissionTicketTemplateVariable(currentUser,
                            admissionTicketInfoId, templateId,
                            AdmissionTicketTemplateCode.EXAM_NAME, "考试名称",
                            true, admissionTicketInfo.getExamName());
                    admissionTicketTemplateVariables.add(examName);
                    break;
                case AdmissionTicketTemplateCode.EXAM_AGREEMENT:
                    // 初始化考生协议
                    String examId = admissionTicketInfo.getExamId();
                    Task task = iTaskService.getById(examId);
                    String defaultValue;
                    if (Objects.nonNull(task)) {
                        // 虚拟考场
                        defaultValue = iExamAgreementService.getExamAgreement(examId);
                    } else {
                        // 无考场
                        defaultValue = ksFallbackFactoryClient.exam(currentUser.getOfficeid(), deptId, examId).getData().getExamAgreement();
                    }
                    AdmissionTicketTemplateVariable agreement = createAdmissionTicketTemplateVariable(currentUser,
                            admissionTicketInfoId, templateId,
                            AdmissionTicketTemplateCode.EXAM_AGREEMENT, "考生须知",
                            true, defaultValue);
                    admissionTicketTemplateVariables.add(agreement);
                    break;
            }
        }
        saveBatch(admissionTicketTemplateVariables);
    }

    /**
     * 获取考生协议
     *
     * @param admissionTicketInfoId
     * @return
     */
    @Override
    public String getExamAgreement(String admissionTicketInfoId) {
        return lambdaQuery().eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionTicketInfoId)
                .list()
                .stream()
                .filter(admissionTicketTemplateVariable -> AdmissionTicketTemplateCode.EXAM_AGREEMENT.equals(admissionTicketTemplateVariable.getVariableCode()))
                .findFirst()
                .map(AdmissionTicketTemplateVariable::getVariableDefaultValue).orElse(null);

    }

    /**
     * 同步考生协议
     *
     * @param examId
     * @param loginUser
     */
    @Override
    public void syncExamAgreement(String examId, User loginUser) {
        log.info("更新考试协议：{} {}", examId, loginUser);
        Task task = iTaskService.getById(examId);
        String examAgreement;
        if (Objects.nonNull(task)) {
            // 虚拟考场
            examAgreement = iExamAgreementService.getExamAgreement(examId);
        } else {
            // 无考场
            examAgreement = ksFallbackFactoryClient.exam(loginUser.getOfficeid(), loginUser.getOrganizationid(), examId).getData().getExamAgreement();
        }
        updateExamAgreementByExamId(examId, examAgreement, loginUser);
    }

    /**
     * 更新考试协议
     *
     * @param examId
     * @param examAgreement
     * @param loginUser
     */
    private void updateExamAgreementByExamId(String examId, String examAgreement, User loginUser) {
        log.info("更新考试协议：{} {} {}", examId, examAgreement, loginUser);
        AdmissionTicketInfo byExamId = iAdmissionTicketInfoService.getByExamId(examId);
        if (Objects.nonNull(byExamId)) {
            String admissionId = byExamId.getId();
            lambdaUpdate()
                    .eq(AdmissionTicketTemplateVariable::getDelFlag, false)
                    .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionId)
                    .eq(AdmissionTicketTemplateVariable::getVariableCode, AdmissionTicketTemplateCode.EXAM_AGREEMENT)
                    .set(AdmissionTicketTemplateVariable::getVariableDefaultValue, examAgreement)
                    .set(AdmissionTicketTemplateVariable::getUpdateBy, loginUser.getId())
                    .set(AdmissionTicketTemplateVariable::getUpdateDate, LocalDateTime.now())
                    .update();
        }
    }

    /**
     * 更新无考场考生协议
     *
     * @param kwExamVO
     * @param userId
     */
    @Override
    public void updateKwExamAgreement(KwExamVO kwExamVO, String userId) {
        log.info("[准考证][无考场][考生数据同步][考试更新]更新考试协议：{} {}", kwExamVO, userId);
        AdmissionTicketInfo byExamId = iAdmissionTicketInfoService.getByExamId(kwExamVO.getId());
        if (Objects.nonNull(byExamId)) {
            String admissionId = byExamId.getId();
            lambdaUpdate()
                    .eq(AdmissionTicketTemplateVariable::getDelFlag, false)
                    .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionId)
                    .eq(AdmissionTicketTemplateVariable::getVariableCode, AdmissionTicketTemplateCode.EXAM_AGREEMENT)
                    .set(AdmissionTicketTemplateVariable::getVariableDefaultValue, kwExamVO.getExamAgreement())
                    .set(AdmissionTicketTemplateVariable::getUpdateBy, userId)
                    .set(AdmissionTicketTemplateVariable::getUpdateDate, LocalDateTime.now())
                    .update();
        }
    }

    /**
     * 更新无考场考试名称
     *
     * @param kwExamVO
     * @param userId
     */
    @Override
    public void updateKwExamName(KwExamVO kwExamVO, String userId) {
        log.info("[准考证][无考场][考生数据同步][考试更新]更新考试名称：{} {}", kwExamVO, userId);
        AdmissionTicketInfo byExamId = iAdmissionTicketInfoService.getByExamId(kwExamVO.getId());
        if (Objects.nonNull(byExamId)) {
            String admissionId = byExamId.getId();
            lambdaUpdate()
                    .eq(AdmissionTicketTemplateVariable::getDelFlag, false)
                    .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionId)
                    .eq(AdmissionTicketTemplateVariable::getVariableCode, AdmissionTicketTemplateCode.EXAM_NAME)
                    .set(AdmissionTicketTemplateVariable::getVariableDefaultValue, kwExamVO.getExamName())
                    .set(AdmissionTicketTemplateVariable::getUpdateBy, userId)
                    .set(AdmissionTicketTemplateVariable::getUpdateDate, LocalDateTime.now())
                    .update();
        }
    }
}
